﻿using Entity.Models;
using HuaRunInterface.Comm;
using HuaRunInterface.Models;
using HuaRunLanYanInterface.Controllers.RollbackControllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Utility;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace HuaRunLanYanInterface.Controllers
{
    public delegate void UpdateBalance(object model);

    [Route("api/BLL/PostPay/BalanceSync")]
    [ApiController]
    public class BalanceSyncController : ControllerBase
    {
        public static UpdateBalance Balance = new UpdateBalance(GetUpdateBalace);
        private static ResBalanceModel ResObject;
        private static bool Success = false;
        private static string sequence = "";
        public static void GetUpdateBalace(object obj)
        {
            try
            {
                WriteLog.WriteLogFile($"get update balace : {obj.SerializerObjectToString()}");
                string? conn = Global.Configuration["ConnectionStrings:DDb"];
                using (Entity.DBContext context = Entity.BaseContext.CreateContext(conn))
                {
                    JObject job = JObject.Parse(obj.SerializerObjectToString());
                    MeterInfo? v = context.meterInfos.Where(p => p.uniqueDeviceIdentifier == job["uniqueDeviceIdentifier"].ToString()).FirstOrDefault();
                    if (v != null)
                    {
                        ReqRemainMoneyModel model = (ReqRemainMoneyModel)obj;
                        ResBalanceModel res = new ResBalanceModel();
                        res.MeterCommNo = v.meterCode;
                        res.BalanceResult = true;
                        res.ShowRemain = true;
                        res.RemainType = 0;
                        if (model.cmdParam != null)
                        {
                            res.RemainValue = (decimal)model.cmdParam.settlementBalance;
                            res.ValveCtrl = GetValveCtrl(model.cmdParam.valveControlState);
                            res.Price = (decimal)model.cmdParam.unitPrice;
                        }
                        res.ShowPrice = true;
                        Success = true;
                        sequence = model.sequence;
                        ResObject = res;
                    }
                    RTUInfo? rTUInfo = context.rTUInfos.Where(p => p.uniqueDeviceIdentifier == job["uniqueDeviceIdentifier"].ToString()).FirstOrDefault();
                    if (rTUInfo != null)
                    {
                        ReqRtuRemainMoneyModel model = (ReqRtuRemainMoneyModel)obj;
                        ResBalanceModel res = new ResBalanceModel();
                        res.MeterCommNo = rTUInfo.deviceCode;
                        res.BalanceResult = true;
                        res.ShowRemain = true;
                        res.RemainType = 0;
                        if (model.cmdParam != null)
                        {
                            res.RemainValue = (decimal)model.cmdParam.settlementBalance;
                            res.ValveCtrl = GetValveCtrl(model.cmdParam.valveControlState);
                            res.Price = (decimal)model.cmdParam.unitPrice;
                        }
                        res.ShowPrice = true;
                        Success = true;
                        sequence = model.sequence;
                        ResObject = res;
                    }
                }
            }
            catch (Exception ex)
            {
                WriteLog.WriteExceptionFile("Get Update Balace : " + ex.Message + "\r\n" + ex.StackTrace);
            }
        }

        private static int GetValveCtrl(string key)
        {
            int value = 0;
            //DEFAULT：默认不控阀
            //OPEN：   开阀
            //CLOSE：  关阀
            //ALARM_CLOSE：  预警关阀
            switch (key)
            {
                case "OPEN":
                    value = 1;
                    break;
                case "CLOSE":
                    value = 2;
                    break;
                case "ALARM_CLOSE":
                    value = 3;
                    break;
                default: break;
            }
            return value;
        }

        // GET: api/BalanceSync
        [HttpGet]
        public ContentResult Get(object value)
        {
            return BalanceSync(value);
        }

        // POST: api/BalanceSync
        [HttpPost]
        public ContentResult Post([FromBody] object value)
        {
            return BalanceSync(value);
        }

        private ContentResult BalanceSync(object obj)
        {
            ResBaseModel3 res = new ResBaseModel3();
            try
            {
                ReqBalanceModel req= obj.ToString().JSONStringToObject<ReqBalanceModel>();
                WriteLog.WriteBalanceLogsFile("api balance sync value: " + req.SerializerObjectToString());
                string conn = Global.Configuration["ConnectionStrings:DDb"];
                using (Entity.DBContext context = Entity.BaseContext.CreateContext(conn))
                {
                    MeterInfo? m = context.meterInfos.Where(p => p.meterCode == req.meter_comm_no && p.IsDelete != 1).FirstOrDefault();
                    RTUInfo? rTUInfo = context.rTUInfos.Where(p => p.deviceCode == req.meter_comm_no && p.IsDelete != 1).FirstOrDefault();
                    if (m == null && rTUInfo == null)
                    {
                        res.State = "success";
                        res.Message = "没有当前设备";
                        return Content(JsonConvert.SerializeObject(res));
                    }
                    else
                    {
                        string apiAddress = "";
                        string errMsg = "";
                        bool result = false;
                        if (m != null)
                        {
                            apiAddress = "eciot-openapi/meter/read";
                            MeterDataUpModel data = new MeterDataUpModel();
                            data.transaction = Guid.NewGuid().ToString();
                            data.body = new List<meterReadingDetails>();
                            meterReadingDetails mrd = new meterReadingDetails();
                            mrd.sequence = "Read" + DateTime.Now.ToString("yyMMddHHmmssff");
                            mrd.domainId = Global.DomainId;
                            mrd.conMeterCode = req.meter_comm_no;
                            mrd.uniqueDeviceIdentifier = m.uniqueDeviceIdentifier;
                            mrd.meterFactoryCode = Global.Configuration["AppSettings:FactoryCode"];
                            mrd.readNum = (double)req.std_sum;
                            mrd.readStatus = 1;
                            mrd.readTime = req.acquisition_time;
                            mrd.standarTotaldFlow = (double)req.std_sum;
                            mrd.signalQuality = req.rssi;
                            mrd.valveStatus = req.valve_open ? 0 : 1;
                            data.body.Add(mrd);
                            result = Global.CommonSend(apiAddress, data, ref errMsg);
                        }
                        if (rTUInfo != null)
                        {
                            apiAddress = "eciot-openapi/industry/meter/read";
                            RtuDataUpModel rData = new RtuDataUpModel();
                            rData.transaction = Guid.NewGuid().ToString();
                            rData.body = new List<RtuReadingDetails>();
                            RtuReadingDetails body = new RtuReadingDetails();
                            body.sequence = "Read" + DateTime.Now.ToString("yyMMddHHmmssff");
                            body.domainId = Global.DomainId;
                            body.deviceCode = rTUInfo.deviceCode;
                            body.deviceType = rTUInfo.deviceType;
                            body.uniqueDeviceIdentifier = rTUInfo.uniqueDeviceIdentifier;
                            body.standardNum = (double)req.std_sum;
                            body.workNum = (double)req.std_sum;
                            body.meterFactoryCode = Global.Configuration["AppSettings:FactoryCode"];
                            body.valveStatus = req.valve_open ? 0 : 1;
                            body.signalQuality = req.rssi;
                            body.readTime = req.acquisition_time;
                            rData.body.Add(body);
                            result = Global.CommonSend(apiAddress, rData, ref errMsg);
                        }
                      
                        WriteLog.WriteBalanceLogsFile($"BalanceSyncController meter data upload : {result};msg:{errMsg}");
                        if (result)
                        {
                            System.Threading.Thread.Sleep(500);
                            int count = 0;
                            while (true)
                            {
                                count++;
                                if (Success && ResObject != null && ResObject.MeterCommNo == req.meter_comm_no)
                                {
                                    count = 10;
                                    res.State = "success";
                                    res.Message = "成功";
                                    res.Data = ResObject;

                                    CommandResponseModel mr = new CommandResponseModel();
                                    mr.sequence = sequence;
                                    mr.commandEndTime = DateTime.Now;
                                    mr.success = true;
                                    mr.commandResult = "成功";
                                    result = Global.CommonSend("eciot-openapi/cmdResponse", mr, ref errMsg);
                                    WriteLog.WriteBalanceLogsFile($"meter cmdResponse : {result};msg:{errMsg}");
                                    Success = false;
                                    ResObject = null;
                                    sequence = "";

                                }
                                else
                                {
                                    System.Threading.Thread.Sleep(200);
                                }
                                if (count >= 10)
                                    break;
                            };
                        }
                        else
                        {
                            res.State = "failed";
                            res.Message = "失败";
                            return Content(JsonConvert.SerializeObject(res));
                        }
                        WriteLog.WriteBalanceLogsFile($"结算数据推送物联网返回数据：{JsonConvert.SerializeObject(res)}; BalanceSync Get value: {req.SerializerObjectToString()};Remain Money Sync value: {ResObject.SerializerObjectToString()}");
                    }
                }
            }
            catch (Exception ex)
            {
                WriteLog.WriteExceptionFile("api balance sync : " + ex.Message + "\r\n" + ex.StackTrace);
            }
            return Content(JsonConvert.SerializeObject(res));
        }
    }

    public class ReqBalanceModel
    {
        public string meter_comm_no { get; set; }//String 通信号，物联网表 14 位，无线表 10 位
        public DateTime acquisition_time { get; set; }//Datetime 采集时间
        public decimal std_sum { get; set; }//Decimal(18,3) 标况总累计量（本次抄表读数）
        public int battery_level { get; set; }//Int 电量
        public int rssi { get; set; }//Int 信号强度
        public bool valve_open { get; set; }//Bool 阀门状态,true-开阀、false-关阀
    }

    public class ResBalanceModel
    {
        public string MeterCommNo { get; set; }//String 通信号 物联网表 14 位，无线表 10 位
        public bool BalanceResult { get; set; }//Bool 结算状态 false-不结算，true-正常结算
        public bool ShowRemain { get; set; }//Bool 是否显示剩余值 true-显示剩余值，false-不显示剩余值
        public int RemainType { get; set; }//Int 剩余值数据类型 0-剩余金额，1-剩余量
        public decimal RemainValue { get; set; }//Decimal(18,3) 剩余值
        public int ValveCtrl { get; set; }//Int 阀门指令 0-不控制阀门1-开阀2-关阀3-报警关阀（按键可开）4-透支关阀
        /// <summary>
        /// 结算价格
        /// </summary>
        public decimal? Price { get; set; } = null;
        /// <summary>
        /// 累计充值金额
        /// </summary>
        public decimal? TotalChargeMoney { get; set; } = null;

        /// <summary>
        /// 是否显示价格
        /// </summary>
        public bool? ShowPrice { get; set; } = false;
        /// <summary>
        /// 是否显示总充量
        /// </summary>
        public bool? ShowTotalCharge { get; set; } = false;
    }

    public class CommandResponseModel
    {
        public CommandResponseModel()
        {
            success = false;
        }
        public string sequence { get; set; }//String  Y 业务序列（命令推送上传的sequence）
        public string cmdStatus { get; set; }//String  N 命令状态：默认为空，如果该字段不为空则使用该字段判断命令执行状态，如果为空则使用success字段判断命令执行状态
                                             //3: 执行成功
                                             //4: 执行失败
                                             //5: 命令取消
                                             //6: 命令失效(例如互斥、取消等)
        public DateTime commandEndTime { get; set; }//Date    Y 命令结束时间（yyy-MM-dd HH:mm:ss）
        public bool success { get; set; }//boolean Y 是否成功：true：成功，false:失败
        public string commandResult { get; set; }//String Y   命令回执信息
        public string msg { get; set; }//String N   备注
    }
}